import React from 'react';
import { Radio } from 'antd';
//import './App.css';
import 'antd/dist/antd.css';
import "./game.scss";




const optionsRadioGroup = [
  { label: '玩家先手', value: 'man' },
  { label: '电脑先手', value: 'pc' },
];


function Square(props) {

  const XStyle = {
    color: 'cadetblue'
  };
  const OStyle = {
    color: 'chocolate'
  };

  return (
    <button className="square" onClick={props.onClick} style={props.value == 'X' ? XStyle : OStyle}>
      {props.value}
    </button>
  );
}

class Board extends React.Component {

  renderSquare(i) {
    return <Square
      value={this.props.squares[i]}
      onClick={() => this.props.onClick(i)} />;
  }

  render() {
    return (
      <div >
        <div className="board-row">
          {this.renderSquare(0)}
          {this.renderSquare(1)}
          {this.renderSquare(2)}
        </div>
        <div className="board-row">
          {this.renderSquare(3)}
          {this.renderSquare(4)}
          {this.renderSquare(5)}
        </div>
        <div className="board-row">
          {this.renderSquare(6)}
          {this.renderSquare(7)}
          {this.renderSquare(8)}
        </div>
      </div>
    );
  }
}

class Game extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      history: [{
        squares: Array(9).fill(null),
      }],
      xIsNext: true,
      stepNumber: 0,
      selectedValue: 'man',
    };
  }


  handleClick(i) {
    const history = this.state.history.slice(0, this.state.stepNumber + 1);
    const current = history[history.length - 1];
    const squares = current.squares.slice();
    if (calculateWinner(squares) || squares[i]) {
      return;
    }

    squares[i] = this.state.xIsNext ? 'X' : 'O';


    this.setState({
      history: history.concat([{
        squares: squares,
      }]),
      xIsNext: !this.state.xIsNext,
      stepNumber: history.length,
    }, () => {
      this.AItodo()
    })

  }


  handleRadioChange = e => {
    console.log(e.target.value);
    this.jumpTo(0)
    this.setState({
      selectedValue: e.target.value,
    });
  };

  AItodo() {
    const history = this.state.history.slice(0, this.state.stepNumber + 1);
    const current = history[history.length - 1];
    const squares = current.squares.slice();
    //console.log(squares)

    if (calculateWinner(squares)) {
      return;
    }


    // 获得所有可能的位置，利用 shuffle 加入随机性
    const availablePos = shuffleArray(getAvailablePos(squares));



    let aiToken = this.state.xIsNext ? 'X' : 'O';
    let gameAI = new GameAI(squares, aiToken, 0);

    gameAI.getScore();

    const res = gameAI.nextMove()
    //console.log(res);

    //squares[availablePos[0]] = this.state.xIsNext ? 'X' : 'O';

    this.setState({
      history: history.concat([{
        squares: res,
      }]),
      xIsNext: !this.state.xIsNext,
      stepNumber: history.length,
    })
  }


  jumpTo(step) {

    if (step == 0) {

      this.setState({
        history: [{
          squares: Array(9).fill(null),
        }],
        xIsNext: true,
        stepNumber: 0,
      }, () => {
        if (this.state.selectedValue === 'pc') {
          this.AItodo();
        }
      })

    } else {

      if (step == -2) {



        //console.log(this.state.stepNumber + step)
        if (this.state.selectedValue === 'pc') {
          if (this.state.stepNumber + step <= 0) {
            return null
          }
        } else {
          if (this.state.stepNumber == 9) {
            step = -1;
          }
          if (this.state.stepNumber + step == -1) {
            this.state.stepNumber = 2;
          } else if (this.state.stepNumber + step < -1) {
            return null
          }
        }

        // if (this.state.stepNumber + step <= 0) {
        //   return null
        // }


      }

      if (step == 2) {
        if (this.state.stepNumber + step >= this.state.history.length) {
          return null
        }
      }



      this.setState({
        stepNumber: this.state.stepNumber + step,
        xIsNext: ((this.state.stepNumber + step) % 2) === 0,
      });

    }

  }

  render() {

    const history = this.state.history;
    const current = history[this.state.stepNumber];
    const winner = calculateWinner(current.squares);

    let status;
    if (winner) {

      if (winner == '平局') {
        status = '平局'
      } else {
        status = '获胜者: ' + (this.state.xIsNext == winner ? '玩家' : '电脑');
      }

    } else {
      status = '玩家使用: ' + (this.state.xIsNext ? 'X' : 'O');
    }

    return (
      <div className="game">
        <div className="status">{status}</div>

        <div className="game-board">
          <Board
            squares={current.squares}
            onClick={(i) => this.handleClick(i)} />
        </div>

        <Radio.Group
          style={{ marginTop: 20 }}
          options={optionsRadioGroup}
          onChange={this.handleRadioChange}
          value={this.state.selectedValue}
          optionType="button"
          buttonStyle="solid"
        />

        <div className="game-info">

          <button className="menu" onClick={() => this.jumpTo(-2)}>
            悔棋
            </button>

          <button className="menu" onClick={() => this.jumpTo(0)}>
            重新开始
          </button>

          {/* <button className="menu" onClick={() => this.jumpTo(2)}>
            下一步
            </button> */}

        </div>
      </div>
    );
  }
}
export default Game;




function calculateWinner(squares) {
  const lines = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6],
  ];
  for (let i = 0; i < lines.length; i++) {
    const [a, b, c] = lines[i];
    if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
      return squares[a];
    }
  }
  if (getAvailablePos(squares).length == 0) {
    return '平局';
  }
  return null;
}

//找出当前仍可以下子的位置
function getAvailablePos(squares) {
  const result = [];
  squares.forEach((ele, index) => {
    if (!ele) {
      result.push(index);
    }
  });
  return result;
}

//打乱数组
function shuffleArray(array) {
  let i = array.length - 1;
  for (; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    const temp = array[i];
    array[i] = array[j];
    array[j] = temp;
  }
  return array;
}


function changeTurn(player) {
  return player === 'X' ? 'O' : 'X';
}


//给出一个位置，返回一个新的 board
function generateNewBoard(pos, player, board) {
  const newBoard = board.slice();
  newBoard[pos] = player;
  return newBoard;
}

class GameAI {
  constructor(board, player, depth, alpha, beta) {
    this.board = board;
    this.playerTurn = player;
    this.choosenState = null;
    this.alpha = alpha || -Infinity;
    this.beta = beta || Infinity;
    this.depth = depth;
  }

  getScore() {
    const aiToken = 'O';

    const winner = calculateWinner(this.board);


    if (winner) {
      if (winner === '平局') return 0;
      if (winner === aiToken) return 10;
      return -10;
    }

    // 到达了最大深度后的相应处理
    //console.log('this.depth=' + this.depth)
    if (this.depth > 100) {
      return 0;
    }

    // 获得所有可能的位置，利用 shuffle 加入随机性
    const availablePos = shuffleArray(getAvailablePos(this.board));

    // 对于 max 节点，返回的是子节点中的最大值
    if (this.playerTurn === aiToken) {

      let maxScore = -1000;
      let maxIndex = 0;

      for (let i = 0; i < availablePos.length; i++) {
        const pos = availablePos[i];
        const newBoard = generateNewBoard(pos, this.playerTurn, this.board);

        const childState = new GameAI(newBoard, changeTurn(this.playerTurn), this.depth + 1, this.alpha, this.beta);
        const childScore = childState.getScore();

        if (childScore > maxScore) {
          maxScore = childScore;
          maxIndex = i;
          this.choosenState = childState;
          this.alpha = maxScore;
        }

        if (this.alpha >= this.beta) {
          break;
        }
      }

      //console.log('max 节点 maxIndex=' + maxIndex)
      return maxScore;
    } else {
      // 对于 min 节点，返回的是子节点中的最小值
      let minScore = 1000;
      let minIndex = 0;

      for (let i = 0; i < availablePos.length; i++) {
        const pos = availablePos[i];
        const newBoard = generateNewBoard(pos, this.playerTurn, this.board);

        const childState = new GameAI(newBoard, changeTurn(this.playerTurn), this.depth + 1, this.alpha, this.beta);
        const childScore = childState.getScore();

        if (childScore < minScore) {
          minScore = childScore;
          minIndex = i;
          this.choosenState = childState;
          this.beta = minScore;
        }

        if (this.alpha >= this.beta) {
          break;
        }
      }
      //console.log('min 节点 minIndex=' + minIndex)
      return minScore;
    }
  }

  nextMove() {
    return this.choosenState.board;
  }

}


